﻿
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long L64;

class PrintOut
{
    char con[32];
    int top;

public:
    PrintOut& operator()(char x) {
        cout << "char: " << x << endl;
        return *this;
    }
    PrintOut& operator()(int x) {
        cout << "int: ";
        return operator()(static_cast<L64>(x));
    }
    PrintOut& operator()(L64 x) {
        cout << "long long: ";
        if (x == 0) { putchar('0'); }
        if (x < 0) { putchar('-'); x = -x; }
        top = sizeof(con) - 1;
        con[top] = 0;
        while (x > 0) {
            con[--top] = x % 10 + '0';
            x /= 10;
        }
        cout << &con[top] << endl;
        return *this;
    }
    PrintOut& operator()(float x) { 
        cout << "float: ";
        printf("%g\n", x);
        return *this; 
    }
    PrintOut& operator()(double x) {
        cout << "double: "<<x<<endl;
        return *this;
    }
    PrintOut& operator()(double x, int k) {
        cout << "double[" << k << "]: ";
        sprintf(con, "%%.%df\n", k);
        printf(con, x); 
        return *this;
    }
    PrintOut& operator()(const char* x) {
        cout << "const char*: ";
        cout << x << endl;
        return *this;
    }
    PrintOut& operator()(const string x) {
        cout << "string: ";
        return operator()(x.data());
    }
    template <class T>
    PrintOut& operator()(T x) { 
        cout << typeid(x).name() << ": " << x << endl; 
        return *this;
    }
};

class MyPoint
{
public:
    MyPoint(double x, double y, double z) { _x = x; _y = y; _z = z; }

private:
    double _x, _y, _z;
    friend ostream& operator<<(ostream& o, MyPoint t) {
        return o << "(" << t._x << "," << t._y << "," << t._z << ")";
    }
};

struct MyLine
{
    double _k, _b;
    friend ostream& operator<<(ostream& o, MyLine t) {
        return o << "y = " << t._k << "x + " << t._b;
    }
};


struct Pair {
    int n; string s;
    friend ostream& operator<< (ostream& os, const Pair& p) {
        return os << "{ " << p.n << ", " << p.s.data() << " }";
    }
};

int main() {

    PrintOut prt;
    prt('c')(12)(1234567890123467890);
    prt(45.f)(45.6789)(1.23456789e80)(45.6789, 1);
    prt("This is my test.")(string("The test is ok."));
    prt(12345678901234678901ul);

    MyPoint pt(3, 4, 6);
    MyLine ln{ 4, 6 };
    Pair pr1{ 1, "Monday" };
    prt(pt)(ln)(pr1);

    const std::vector<Pair> v{ pr1, {2, "Tuesday "}, {3, "Wednesday"}, {4, "Thursday"}, {5, "Friday "}, {6, "Saturday"}, {7, "Sunday"} };
    for_each(v.begin(), v.end(), prt);

    char is[33];
    for_each(is, is + sizeof(is), [](char& c) {c = rand() % 26 + 'A';});
    for_each(is, is + sizeof(is), prt);
}